<?php
/**
 * Dance-Tunes API Client
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled
 * with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.inphpwetrust.com/dance-tunes-public-api-a-php-client-library#new-bsd-license
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to blog@inphpwetrust.com so we can send you a copy immediately.
 *
 * @category   Dancetunes
 * @package    Dancetunes
 * @copyright  Copyright (c) 2010 George Enciu  (http://www.colorsoft.ro, http://www.inphpwetrust.com)
 * @license    http://www.inphpwetrust.com/dance-tunes-public-api-a-php-client-library#new-bsd-license
 */

/**
 * @category   Dancetunes
 * @package    Dancetunes
 * @copyright  Copyright (c) 2010 George Enciu  (http://www.colorsoft.ro, http://www.inphpwetrust.com)
 * @license    http://www.inphpwetrust.com/dance-tunes-public-api-a-php-client-library#new-bsd-license
 */

class Dancetunes {
	/**
	 * The session key received from the server
	 * 
	 * @var string
	 */
	protected $_sessionKey = null;
	/**
	 * The API key assigned to the user
	 * 
	 * @var string
	 */
	protected $_apiKey = null;
	/**
	 * The username
	 * 
	 * @var string
	 */
	protected $_userName = null;
	/**
	 * The user's password
	 * 
	 * @var string
	 */
	protected $_password = null;
	
	/**
	 * API endpoint
	 * 
	 * @var string
	 */
	const URL = 'http://main.dance-tunes.com/idt/pk_user_api.request?p_message=';
	const VESRION = '';
	
	/**
	 * The class constructor
	 * The class can be instantiated with just the required API key. 
	 * The other params can be passed by their setters
	 * 
	 * @param string $apiKey
	 * @param string $user
	 * @param string $pass
	 * @param string $sessionKey
	 */
	public function __construct($apiKey, $user = null, $pass = null, $sessionKey = null) {
		$this->_apiKey = $apiKey;
		$this->_userName = $user;
		$this->_password = $pass;
		$this->_sessionKey = $sessionKey;
	}
	
	/**
	 * API Key setter
	 * 
	 * @param string $_apiKey
	 */
	public function setApiKey($_apiKey) {
		$this->_apiKey = $_apiKey;
	}
	
	/**
	 * Password setter
	 * 
	 * @param string $_password
	 */
	public function setPassword($_password) {
		$this->_password = $_password;
	}
	
	/**
	 * Session key setter 
	 * 
	 * @param string $_sessionKey
	 */
	public function setSessionKey($_sessionKey) {
		$this->_sessionKey = $_sessionKey;
	}
	
	/**
	 * Username setter 
	 * 
	 * @param string $_userName
	 */
	public function setUserName($_userName) {
		$this->_userName = $_userName;
	}
	
	/**
	 * Parses an array with a request param in order to obtain the request string
	 * 
	 * @param array $params
	 * @return string
	 */
	protected function parseArrayParams(array $params) {
		$pattern = '<%s>%s</%s>';
		
		$output = '';
		foreach ( $params as $tag => $value ) {
			if (is_array ( $value )) {
				foreach ( $value as $element ) {
					$output .= sprintf ( $pattern, $tag, $element, $tag );
				}
			} else {
				$output .= sprintf ( $pattern, $tag, $value, $tag );
			}
		}
		return urlencode ( $output );
	}
	
	/**
	 * Calls the API endpoint and returns either a SimpleXMLElement object or the request body
	 * 
	 * @param string $cmd
	 * @param array $params
	 * @return SimpleXMLElement|string
	 */
	protected function call($cmd, array $params) {
		$params ['cmd'] = $cmd;
		if ($this->_sessionKey != NULL) {
			$params ['session'] = $this->_sessionKey;
		}
		
		$queryString = $this->parseArrayParams ( $params );
		try {
			$http = new Zend_Http_Client ( self::URL . $queryString );
			$response = $http->request ();
			
			$headers = $response->getHeaders ();
			if (strstr ( $headers ['Content-type'], 'text/html' )) {
				$data = simplexml_load_string ( $response->getBody () );
				if ($data->error != '') {
					throw new Zend_Exception ( $data->error, 0 );
				}
				return $data;
			} else {
				return $response->getBody ();
			}
		} catch ( Zend_Exception $ex ) {
			throw $ex;
		}
	}
	
	/**
	 * Wrapper method for API Authentication 
	 * 
	 * @link http://www.dance-tunes.com/api/authentication.html#description
	 * @return bool|string
	 */
	public function authenticate() {
		$params = array ('key' => $this->_apiKey, 'username' => $this->_userName, 'password' => $this->_password );
		
		$response = $this->call ( 'authentication', $params );
		
		if ($response instanceof SimpleXMLElement) {
			if ($response->security->session != '') {
				return $this->_sessionKey = $response->security->session;
			}
		}
		return false;
	}
	
	/**
	 * Wrapper method for get_tune_info API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_tune_info.html#description
	 * @param int $tuneId
	 * @return Dancetunes_TuneInfo
	 */
	public function getTuneInfo($tuneId) {
		if (! is_numeric ( $tuneId )) {
			throw new Zend_Exception ( "Parameter 'tuneId' should be a number" );
		}
		$params = array ('tun_id' => $tuneId );
		
		$response = $this->call ( 'get_tune_info', $params );
		return new Dancetunes_TuneInfo ( $response );
	
	}
	
	/**
	 * Wrapper method for get_album_info API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_album_info.html#description
	 * @param int $albumId
	 * @return Dancetunes_AlbumInfo
	 */
	public function getAlbumInfo($albumId) {
		if (! is_numeric ( $albumId )) {
			throw new Zend_Exception ( "Parameter 'albumId' should be a number" );
		}
		
		$params = array ('alb_id' => $albumId );
		
		$response = $this->call ( 'get_album_info', $params );
		return new Dancetunes_AlbumInfo ( $response );
	}
	
	/**
	 * Wrapper method for get_genre_info API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_genre_info.html#description
	 */
	public function getGenreInfo() {
		$response = $this->call ( 'get_genre_info', array () );
		return new Dancetunes_AlbumInfo ( $response );
	}
	
	/**
	 * Wrapper method for get_new_releases API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_new_releases.html#description
	 * @param int $genreId
	 * @param int $count
	 * @param int $from
	 * @param int $till
	 * @return Dancetunes_NewReleases
	 */
	public function getNewReleases($genreId, $count, $from, $till) {
		
		if (! is_numeric ( $genreId )) {
			throw new Zend_Exception ( "Parameter 'genreId' should be a number" );
		}
		if (! is_numeric ( $count )) {
			throw new Zend_Exception ( "Parameter 'count' should be a number" );
		}
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('sge_id' => $genreId, 'count' => $count, 'from' => $from, 'till' => $till );
		
		$response = $this->call ( 'get_new_releases', $params );
		return new Dancetunes_NewReleases ( $response );
	}
	
	/**
	 * Wrapper method for get_just_added API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_just_added.html#description
	 * @param int $genreId
	 * @param int $count
	 * @param int $from
	 * @param int $till
	 * @return Dancetunes_JustAdded
	 * @throws Zend_Exception
	 */
	public function getJustAdded($genreId, $count, $from, $till) {
		if (! is_numeric ( $genreId )) {
			throw new Zend_Exception ( "Parameter 'genreId' should be a number" );
		}
		if (! is_numeric ( $count )) {
			throw new Zend_Exception ( "Parameter 'count' should be a number" );
		}
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('sge_id' => $genreId, 'count' => $count, 'from' => $from, 'till' => $till );
		
		$response = $this->call ( 'get_just_added', $params );
		return new Dancetunes_JustAdded ( $response );
	}
	
	/**
	 * Wrapper method for get_newest_albums API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_newest_albums.html#description
	 * @param int $genreId
	 * @param int $count
	 * @param int $from
	 * @param int $till
	 * @return Dancetunes_NewestAlbums
	 * @throws Zend_Exception
	 */
	public function getNewestAlbums($genreId, $count, $from, $till) {
		if (! is_numeric ( $genreId )) {
			throw new Zend_Exception ( "Parameter 'genreId' should be a number" );
		}
		if (! is_numeric ( $count )) {
			throw new Zend_Exception ( "Parameter 'count' should be a number" );
		}
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('sge_id' => $genreId, 'count' => $count, 'from' => $from, 'till' => $till );
		
		$response = $this->call ( 'get_newest_albums', $params );
		return new Dancetunes_NewestAlbums ( $response );
	}
	
	/**
	 * Wrapper method for get_artist_tune_list API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_artist_tune_list.html#description
	 * @param int $artistId
	 * @param int $count
	 * @param int $from
	 * @param int $till
	 * @return Dancetunes_ArtistTuneList
	 * @throws Zend_Exception 
	 */
	public function getArtistTuneList($artistId, $count, $from, $till) {
		if (! is_numeric ( $artistId )) {
			throw new Zend_Exception ( "Parameter 'artistId' should be a number" );
		}
		
		if (! is_numeric ( $count )) {
			throw new Zend_Exception ( "Parameter 'count' should be a number" );
		}
		
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('art_id' => $artistId, 'count' => $count, 'from' => $from, 'till' => $till );
		
		$response = $this->call ( 'get_artist_tune_list', $params );
		return new Dancetunes_ArtistTuneList ( $response );
	}
	
	/**
	 * Wrapper method for get_label_tune_list API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_label_tune_list.html#description
	 * @param int $labelId
	 * @param int $count
	 * @param int $from
	 * @param int $till
	 * @param string $order
	 * @param string $sort
	 * @return Dancetunes_LabelTuneList
	 * @throws Zend_Exception 
	 */
	public function getLabelTuneList($labelId, $count, $from, $till, $order = '', $sort = '') {
		if (! is_numeric ( $labelId )) {
			throw new Zend_Exception ( "Parameter 'labelId' should be a number" );
		}
		
		if (! is_numeric ( $count )) {
			throw new Zend_Exception ( "Parameter 'count' should be a number" );
		}
		
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('lab_id' => $labelId, 'count' => $count, 'from' => $from, 'till' => $till, 'order' => $order, 'sort' => $sort );
		
		$response = $this->call ( 'get_label_tune_list', $params );
		return new Dancetunes_LabelTuneList ( $response );
	}
	
	/**
	 * Wrapper method for get_tune_info_list API call
	 * 
	 * @link http://www.dance-tunes.com/api/get_tune_info_list.html#description
	 * @param array $tuneList
	 * @return Dancetunes_TuneInfoList
	 */
	public function getTuneInfoList(array $tuneList) {
		$params = array ('tun_id' => $tuneList );
		
		$response = $this->call ( 'get_tune_info_list', $params );
		return new Dancetunes_TuneInfoList ( $response );
	}
	/**
	 * Wrapper method for get_preview API call
	 * Retruns the content of the audio file
	 * 
	 * @link http://www.dance-tunes.com/api/get_preview.html#description
	 * @param int $tuneId
	 * @return string
	 * @throws Zend_Exception
	 */
	public function getPreview($tuneId) {
		if (! is_numeric ( $tuneId )) {
			throw new Zend_Exception ( "Parameter 'tuneId' should be a number" );
		}
		
		$params = array ('tun_id' => $tuneId );
		
		$response = $this->call ( 'get_preview', $params );
		return $response;
	}
	
	/**
	 * Wrapper method for get_picture API call
	 * Retruns the content of the image file
	 * 
	 * @link http://www.dance-tunes.com/api/get_picture.html#description
	 * @param string $type
	 * @param int $id
	 * @return string
	 * @throws Zend_Exception
	 */
	public function getPicture($type, $id) {
		if (! in_array ( $type, array ('AL', 'TU' ) )) {
			throw new Zend_Exception ( "Parameter 'type' should be AL for album or TU for tune" );
		}
		
		if (! is_numeric ( $id )) {
			throw new Zend_Exception ( "Parameter 'id' should be a number" );
		}
		
		$params = array ('type' => $type, 'id' => $id );
		
		$response = $this->call ( 'get_picture', $params );
		return $response;
	}
	
	/**
	 * Wrapper method for search API call
	 * 
	 * @link http://www.dance-tunes.com/api/search.html#description
	 * @param string $string
	 * @param int $from
	 * @param int $till
	 * @param int $order
	 * @param int $sort
	 * @param bool $isTune
	 * @param bool $isMix
	 * @param bool $isAlbum
	 * @param array $field
	 * @return Dancetunes_Search
	 * @throws Zend_Exception
	 */
	public function search($string, $from, $till, $order = '', $sort = '', $isTune = true, $isMix = true, $isAlbum = true, array $fields) {
		if (strlen ( $string ) < 2) {
			throw new Zend_Exception ( "Parameter 'string' should have at least 2 characters" );
		}
		
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		if (! is_bool ( $isTune )) {
			throw new Zend_Exception ( "Parameter 'isTune' should be boolean" );
		}
		
		if (! is_bool ( $isMix )) {
			throw new Zend_Exception ( "Parameter 'isMix' should be boolean" );
		}
		
		if (! is_bool ( $isAlbum )) {
			throw new Zend_Exception ( "Parameter 'isAlbum' should be boolean" );
		}
		
		if (count ( $fields ) == 0) {
			throw new Zend_Exception ( "Parameter 'fields' should contin at least one element" );
		}
		
		$params = array ('string' => $string, 'from' => $from, 'till' => $till, 'order' => $order, 'sort' => $sort, 'ind_tune' => $isTune ? 'y' : 'n', 'ind_mix' => $isMix ? 'y' : 'n', 'ind_album' => $isAlbum ? 'y' : 'n', 'field' => implode ( ',', $fields ) );
		
		$response = $this->call ( 'search', $params );
		return new Dancetunes_Search ( $response );
	}
	
	/**
	 * Wrapper method for search_artists API call
	 * 
	 * @link http://www.dance-tunes.com/api/search_artists.html#description
	 * @param string $string
	 * @param unknown_type $from
	 * @param unknown_type $till
	 * @param unknown_type $sort
	 * @return Dancetunes_SearchArtists
	 */
	public function searchArtists($string, $from, $till, $sort = '') {
		if (strlen ( $string ) < 2) {
			throw new Zend_Exception ( "Parameter 'string' should have at least 2 characters" );
		}
		
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('string' => $string, 'from' => $from, 'till' => $till, 'sort' => $sort );
		
		$response = $this->call ( 'search_artists', $params );
		return new Dancetunes_SearchArtists ( $response );
	}
	
	/**
	 * Wrapper method for search_labels API call
	 * 
	 * @link http://www.dance-tunes.com/api/search_labels.html#description
	 * @param string $string
	 * @param unknown_type $from
	 * @param unknown_type $till
	 * @param unknown_type $sort
	 * @return Dancetunes_SearchLabels
	 */
	public function searchLabels($string, $from, $till, $sort = '') {
		if (strlen ( $string ) < 2) {
			throw new Zend_Exception ( "Parameter 'string' should have at least 2 characters" );
		}
		
		if (! is_numeric ( $from )) {
			throw new Zend_Exception ( "Parameter 'from' should be a number" );
		}
		
		if (! is_numeric ( $till )) {
			throw new Zend_Exception ( "Parameter 'till' should be a number" );
		}
		
		$params = array ('string' => $string, 'from' => $from, 'till' => $till, 'sort' => $sort );
		
		$response = $this->call ( 'search_labels', $params );
		return new Dancetunes_SearchLabels ( $response );
	}
}
